package com.framework.common.util;

import com.framework.common.constant.MenuConstant;
import com.framework.common.api.TreeOper;
import com.framework.common.vo.TreeNode;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class TreeUtils {
    public static <T> List<TreeNode<T>> getTree(List<T> list, TreeOper<T> operator) {
        List<T> topList = list.stream().filter(o -> MenuConstant.ROOT.equals(operator.getParent(o))).collect(Collectors.toList());
        list.removeAll(topList);
        List<TreeNode<T>> parents = new ArrayList<>();
        setChildren(topList, list, parents, operator, 1);
        // 额外处理查询列表中没有上级的数据
        if (list.size() > 0)  {
            List<T> others = new ArrayList<>();
            // 循环每条数据
            list.forEach(o -> {
                others.add(o);
                loopParent(o, others, operator);
            });
            topList = others.stream().filter(o -> MenuConstant.ROOT.equals(operator.getParent(o))).collect(Collectors.toList());
            setChildren(topList, others, parents, operator, 1);
        }
        return parents;
    }

    private static <T> void loopParent(T it, List<T> tops, TreeOper<T> operator) {
        // 获取上级数据
        List<T> parents = operator.getParentList(it);
        if (null!=parents && parents.size() > 0) {
            T parent = parents.get(0);
            long count = tops.stream().filter(o -> operator.getId(o).equals(operator.getId(parent))).count();
            // 已存在，不添加
            if (count > 0) {
                return;
            }
            // 加入数据列表
            tops.add(parent);
            // 如果还有上级，继续获取上级
            if (!"0".equals(operator.getParent(parent))) {
                loopParent(parent, tops, operator);
            }
        }
    }
 
    private static <T> void setChildren(List<T> topList, List<T> allList,  List<TreeNode<T>> treeNode, TreeOper<T> operator, int level) {
        topList.forEach(o -> {
            Optional<TreeNode<T>> optional = treeNode.stream().filter(it -> it.getId().equals(operator.getId(o))).findFirst();
            TreeNode<T> child;
            if (!optional.isPresent()) {
                child = new TreeNode();
                child.setId(operator.getId(o));
                child.setPid(operator.getParent(o));
                child.setName(operator.getName(o));
                child.setLevel(level);
                child.setData(o);
                treeNode.add(child);
            } else {
                child = optional.get();
            }
            List<T> children = allList.stream().filter(c -> operator.getItem(o).equals(operator.getParent(c))).collect(Collectors.toList());
            if (children.size() > 0) {
                allList.removeAll(children);
                child.newChildren();
            }
            setChildren(children, allList, child.getChildren(), operator, level+1);
        });
    }
}
